package gui;

import gameEngine.*;
import gameEngine.SGFGame.WrongSGFFileException;

import javax.swing.*;

import java.awt.*;
import java.awt.event.*;
import java.io.*;

/**
 * @author Wojciech Łopata
 *
 */

public class MainFrame extends JFrame
{
	private static final long serialVersionUID = -3368395844121697294L;
	
	private final JMenuBar menuBar;
	private final JPanel mainPanel;
	
	private final JPanel emptyPanel;
	private final CardLayout mainPanelLayout;
	private final String emptyPanelName = "emptyPanel";
	
	private final LocalGameSettingsPanel localGameSettingsPanel;
	private final String localGameSettingsPanelName = "localGameSettingsPanel";
	
	private final BoardDrawer boardDrower;
	private final GameDrawer gameDrawer;
	private final String gameDrawerName = "gameDrawer";
	
	private final NetGameSettingsPanel netGameSettingsPanel;
	private final String netGameSettingsPanelName = "netGameSettingsPanel";
	
	private final SGFControlPanel sgfPanel;
	private final String sgfPanelName = "sgfPanel";
	
	private final JFileChooser fileChooser;
	
	private Game currentGame;
	private GameInfo currentGameInfo;
	
	public MainFrame()
	{
		setResizable(false);
		setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
		
		// CREATING MENU BAR
		menuBar = new JMenuBar();
		initMenuBar();
		setJMenuBar(menuBar);
		
		mainPanel = new JPanel();
		mainPanelLayout = new CardLayout();
		mainPanel.setLayout(mainPanelLayout);
		
		// CREATING NOOBISH EMPTY PANEL
		emptyPanel = new JPanel();
		mainPanelLayout.addLayoutComponent(emptyPanel, emptyPanelName);
		mainPanel.add(emptyPanel);
		
		localGameSettingsPanel = new LocalGameSettingsPanel(this);
		mainPanelLayout.addLayoutComponent(localGameSettingsPanel, localGameSettingsPanelName);
		mainPanel.add(localGameSettingsPanel);
		
		boardDrower = new BoardDrawer(new Dimension(500, 500));
		gameDrawer = new GameDrawer(boardDrower);
		mainPanelLayout.addLayoutComponent(gameDrawer, gameDrawerName);
		mainPanel.add(gameDrawer);
		
		netGameSettingsPanel = new NetGameSettingsPanel(this);
		mainPanelLayout.addLayoutComponent(netGameSettingsPanel, netGameSettingsPanelName);
		mainPanel.add(netGameSettingsPanel);
		
		fileChooser = new JFileChooser();
		sgfPanel = new SGFControlPanel();
		mainPanelLayout.addLayoutComponent(sgfPanel, sgfPanelName);
		mainPanel.add(sgfPanel);
		
		add(mainPanel);
		setVisible(true);
		pack();
	}
	
	protected BoardDrawer getBoardDrawer()
	{
		return boardDrower;
	}
	
	private void initMenuBar()
	{
		JMenu FileMenu = new JMenu();
		FileMenu.setText("Plik");
		
		JMenuItem NewGameMenuItem = new JMenuItem();
		NewGameMenuItem.setText("Nowa gra");
		NewGameMenuItem.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent evt)
			{
				if(!confirmAction()) return;
				mainPanelLayout.show(mainPanel, localGameSettingsPanelName);
			}
		});
		FileMenu.add(NewGameMenuItem);
		
		JMenuItem JoinGameMenuItem = new JMenuItem();
		JoinGameMenuItem.setText("Dołącz do gry sieciowej");
		JoinGameMenuItem.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent evt)
			{
				if(!confirmAction()) return;
				mainPanelLayout.show(mainPanel, netGameSettingsPanelName);
			}
		});
		FileMenu.add(JoinGameMenuItem);
		
		
		JMenuItem LoadSGFMenuItem = new JMenuItem();
		LoadSGFMenuItem.setText("Wczytaj plik SGF");
		LoadSGFMenuItem.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent evt)
			{
				if(!confirmAction()) return;
				try
				{
					fileChooser.showOpenDialog(mainPanel);
					sgfPanel.loadSGFFile(fileChooser.getSelectedFile());
					mainPanelLayout.show(mainPanel, sgfPanelName);
				} catch (IOException e)
				{
					showMessage("Nie udało się utworzyć pliku");
				} catch (WrongSGFFileException e)
				{
					showMessage("Zły format pliku");
				} catch (NullPointerException e){}
			}
		});
		FileMenu.add(LoadSGFMenuItem);
		menuBar.add(FileMenu);
	}
	
	public boolean confirmAction()
	{
		if(currentGameInfo != null)
		{
			int response = JOptionPane.showConfirmDialog(null, "Przerwać bieżącą grę?", "Potwierdź", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
			switch(response)
			{
				case JOptionPane.YES_NO_OPTION:
					killCurrentGame();
					return true;
				default:
					return false;
			}
		}
		return true;
	}
	
	public void startLocalGame(Game game)
	{
		currentGame = game;
		currentGameInfo = game.getGameInfo();
		game.begin();
		startDrawing();
	}
	
	private void killCurrentGame()
	{
		if(currentGame != null) currentGame.stopGame();
		gameDrawer.stopDrawing();
		currentGame = null;
		currentGameInfo = null;
	}
	
	protected void setGameInfo(GameInfo info)
	{
		killCurrentGame();
		this.currentGameInfo = info;
	}

	protected void startDrawing()
	{
		mainPanelLayout.show(mainPanel, gameDrawerName);
		new Thread()
		{
			@Override
			public void run()
			{
				while(!currentGameInfo.gameStarted())
					try
					{
						synchronized(currentGameInfo)
						{
							currentGameInfo.wait();
						}
					} catch (InterruptedException e)
					{
						killCurrentGame();
						return;
						
					}
				gameDrawer.startDrawing(currentGameInfo);
				synchronized(currentGameInfo)
				{
					while(!currentGameInfo.gameFinished())
					{
						gameDrawer.update();
						try
						{
							currentGameInfo.wait();
						} catch (InterruptedException e)
						{
							killCurrentGame();
							return;
						}
					}
				}
				
				if(currentGameInfo.getGameStatus().equals(GameStatus.SUCCESSFULLY_ENDED))
					new ResultsDialog(currentGameInfo, currentGame).setVisible(true);
				else
				{
					showMessage("Wystąpił błąd: " + currentGameInfo.getGameStatus());
				}
				killCurrentGame();
				
			}
		}.start();
	}
	
	protected void showMessage(String message)
    {
    	JOptionPane.showMessageDialog(this, message);
    }
}
